package com.tsk.example.exception;

import com.tsk.example.result.Result;
import com.tsk.example.result.ResultEnum;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * @author: 黄嘉振
 * @create: 2023/3/7 16:53
 * @description:    与@RestControllerAdvice配合使用时，用于控制全局处理控制器里的异常
 **/
@RestControllerAdvice(basePackages = "com.tsk.example")
public class ExceptionAdvice {

    /**
     * 自定义的业务异常
     * @param exception
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public Result handleBusinessException(BusinessException exception) {
        return Result.failed(exception.getMessage());
    }

    /**
     * 传了值但是不符合要求的场景
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result handleConstraintViolationException(ConstraintViolationException ex) {
        if (StringUtils.hasText(ex.getMessage())) {
            return Result.failed(ResultEnum.VALIDATE_FAILED, ex.getMessage());
        }
        return Result.failed(ResultEnum.VALIDATE_FAILED);
    }

    /**
     * @RequestBody注解，参数校验不通过时异常
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("校验失败：");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append(":")
                    .append(fieldError.getDefaultMessage()).append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        String msg = sb.toString();
        if (StringUtils.hasText(msg)) {
            return Result.failed(ResultEnum.VALIDATE_FAILED, msg);
        }
        return Result.failed(ResultEnum.VALIDATE_FAILED);
    }

    /**
     * @RequestParam注解，但是接口调用时没有传指定的参数
     * 是没有传参数，而不是传了参数但值为null
     * @param ex
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result hadleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
        return Result.failed(ResultEnum.VALIDATE_FAILED, String.format("缺少参数：[%s]",ex.getParameterName(), ""));
    }
}
